/*
    大家知道一部智能手机的基本组成是操作系统（Operating System，我们下面缩写作 OS）和硬件（HardWare）组成。
    所以说如果我要开一个山寨手机工厂，
    那我这个工厂里必须是既准备好了操作系统，也准备好了硬件，才能实现手机的量产。
    考虑到操作系统和硬件这两样东西背后也存在不同的厂商，
    而我现在并不知道我下一个生产线到底具体想生产一台什么样的手机，我只知道手机必须有这两部分组成，
    所以我先来一个抽象类来约定住这台手机的基本组成
*/

// 定义一个抽象工厂 来约束我们的手机有哪些组成
class MobilePhoneFactory {
  // 操作系统接入接口 Ios Android Harmony OS
  createOS() {
    throw new Error("抽象工厂方法只用于约束 不可调用 请重写");
  }

  // 硬件接入接口 触摸屏、麦克风、CPU、电池等
  createHardWare() {
    throw new Error("抽象工厂方法只用于约束 不可调用 请重写");
  }
}

// 抽象工厂(AbstractFactory)是不干活的,它只用于约束
// 具体工厂(ConcreteFactory)才是干活的,它基于抽象工厂来实现具体的逻辑

/*
    当我们明确了生产方案，明确某一条手机生产流水线具体要生产什么样的手机了之后，就可以化抽象为具体，
    比如我现在想要一个专门生产 Android 系统 + 高通硬件的手机的生产线，我给这类手机型号起名叫 FakeStar
    那我就可以为 FakeStar 定制一个具体工厂
*/

// 实现一个 fakeStar  安卓手机
class FakeStarFactory extends MobilePhoneFactory {
  createOS() {
    // 提供安卓系统实例
    return new AndroidOS();
  }

  createHardWare() {
    // 提供安卓硬件实例 例如: 高通芯片
    return new QualcommHardWare();
  }
}

// 操作系统实例 系统分为安卓系统和IOS系统 他们操作硬件的方式都是相似的 只是实现不同
// 定义一个抽象的系统

class OS {
  controlHardWare() {
    //
    throw new Error("抽象工厂方法只用于约束 不可调用 请重写");
  }
}

// 安卓
class AndroidOS extends OS {
  controlHardWare() {
    console.log("用安卓系统操作硬件");
  }
}

// IOS
class AppleOS extends OS {
  controlHardWare() {
    console.log("用IOS的方式操作硬件");
  }
}

// 硬件类产品实例
class HardWare {
  // 手机硬件的共性方法，这里提取了“根据命令运转”这个共性
  operateByOrder() {
    throw new Error("抽象产品方法不允许直接调用，你需要将我重写！");
  }
}

// 高通
class QualcommHardWare {
  operateByOrder() {
    console.log("高通系统操作运转硬件");
  }
}

// 麒麟
class KylinHardWare extends HardWare {
  operateByOrder() {
    console.log("麒麟系统操作运转硬件");
  }
}

// 至此我们的手机 有了系统、硬件 可以组装了
// 组装一个华为的外壳
const HUAWEI = new FakeStarFactory();
console.log("HUAWEI ==> ", HUAWEI);
// 塞入操作系统
const os = HUAWEI.createOS();
console.log("os ===> ", os);
// 塞入硬件
const hardware = HUAWEI.createHardWare();
console.log("hardware ===> ", hardware);
// 现在操作系统 硬件齐全了
// 运行操作系统
os.controlHardWare();
// 操作硬件
hardware.operateByOrder();
